/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

#ifndef JIAJIA_JJEXE_HPP
#define JIAJIA_JJEXE_HPP

#include"jiajiastd.hpp"
#include"arg.hpp"

namespace jiajia{

    class jjexe{
    private:
        jjcallstack mCallStack;

    public:
        bool exe(jjsymtab & tab, jjir & ir){
            jjirnode * node = ir.head();
            jjirnode * next = nullptr;
            msg_t m = msg::success;
            while(node != nullptr){
                next = node->mNext;

                switch(node->mCode){
                case code::ASSIGN:
                    m = ASSIGN(node->value(jjirnode::IR_UNARY_VALUE), node->value(jjirnode::IR_UNARY_RESULT));
                    break;
                case code::NO:
                    m = NO(node->value(jjirnode::IR_UNARY_VALUE), node->value(jjirnode::IR_UNARY_RESULT));
                    break;
                case code::TOBOOL:
                    m = TOBOOL(node->value(jjirnode::IR_UNARY_VALUE), node->value(jjirnode::IR_UNARY_RESULT));
                    break;

                case code::MINUS:
                    m = MINUS(node->value(jjirnode::IR_UNARY_VALUE), node->value(jjirnode::IR_UNARY_RESULT));
                    break;

                case code::ADD:
                case code::SUB:
                case code::MULT:
                case code::DEV:
                    m = REALOP(node->mCode, node->value(jjirnode::IR_EXPR_LHS), node->value(jjirnode::IR_EXPR_RHS), node->value(jjirnode::IR_EXPR_RESULT));
                    break;

                case code::LINK:
                    m = LINK(node->value(jjirnode::IR_EXPR_LHS), node->value(jjirnode::IR_EXPR_RHS), node->value(jjirnode::IR_EXPR_RESULT));
                    break;

                case code::EQ:
                case code::NE:
                case code::GT:
                case code::LT:
                case code::GE:
                case code::LE:
                    m = BOOLOP(node->mCode, node->value(jjirnode::IR_EXPR_LHS), node->value(jjirnode::IR_EXPR_RHS), node->value(jjirnode::IR_EXPR_RESULT));
                    break;
                    
                case code::IFTRUE:
                case code::IFFALSE:
                    m = IF(node->mCode, node->value(jjirnode::IR_IF_COND), node->node(jjirnode::IR_IF_GOTO), &next);
                    break;

                case code::GOTO:
                    m = GOTO(node->node(jjirnode::IR_GOTO), &next);
                    break;

                case code::ARGNEW:
                    m = ARGNEW(mCallStack);
                    break;

                case code::ARGPUSH:
                    m = ARGPUSH(mCallStack, node->value(jjirnode::IR_ARGPUSH_VAL));
                    break;

                case code::CALL:
                    m = CALL(node->func(jjirnode::IR_CALL_FUNC), mCallStack, node->value(jjirnode::IR_CALL_RESULT));
                    break;

                case code::PUSH:
                    m = PUSH(node->value(jjirnode::IR_UNARY_VALUE), node->value(jjirnode::IR_UNARY_RESULT));
                    break;

                case code::AT:
                    m = AT(node->value(jjirnode::IR_EXPR_LHS), node->value(jjirnode::IR_EXPR_RHS), node->value(jjirnode::IR_EXPR_RESULT));
                    break;

                case code::INSERT:
                case code::FIND:
                    m = TABLEOP(node->mCode, node->value(jjirnode::IR_TABLE_LHS), node->str(jjirnode::IR_TABLE_RHS), node->value(jjirnode::IR_TABLE_RESULT));
                    break;

                case code::GINSERT:
                    m = INSERT(tab.global(), node->str(jjirnode::IR_GLOBAL_NAME), node->value(jjirnode::IR_GLOBAL_RESULT));
                    break;

                case code::GFIND:
                    m = FIND(tab.global(), node->str(jjirnode::IR_GLOBAL_NAME), node->value(jjirnode::IR_GLOBAL_RESULT));
                    break;

                default: break;
                }

                if(m != msg::success){
                    log.err(msg::err_info[m]).endl();
                    if(node->mToken.word != lmcc::_empty)
                        log.err(std::move(node->mToken.getLog()));
                    return false;
                }
                // std::cout<<"jjexe node ="<<node<<", next = "<<next<<std::endl;
                node = next;
            }

            return true;
        }        
    };
}

#endif
